package com.example.ssrbac.service.impl;

import com.example.ssrbac.dto.RoleDTO;
import com.example.ssrbac.entity.Permission;
import com.example.ssrbac.entity.Role;
import com.example.ssrbac.repository.PermissionRepository;
import com.example.ssrbac.repository.RoleRepository;
import com.example.ssrbac.service.RoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import java.util.HashSet;
import java.util.Set;

@Service
public class RoleServiceImpl implements RoleService {
    private static final Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PermissionRepository permissionRepository;

    @Override
    @Transactional
    public RoleDTO createRole(RoleDTO roleDTO) {
        logger.info("Creating new role with name: {}", roleDTO.getName());
        if (roleRepository.existsByName(roleDTO.getName())) {
            logger.error("Role name already exists: {}", roleDTO.getName());
            throw new IllegalArgumentException("角色名称已存在");
        }

        Role role = new Role();
        BeanUtils.copyProperties(roleDTO, role);

        if (roleDTO.getPermissionIds() != null && !roleDTO.getPermissionIds().isEmpty()) {
            logger.debug("Assigning {} permissions to role {}", roleDTO.getPermissionIds().size(), roleDTO.getName());
            Set<Permission> permissions = new HashSet<>(permissionRepository.findAllById(roleDTO.getPermissionIds()));
            role.setPermissions(permissions);
        }

        Role savedRole = roleRepository.save(role);
        logger.info("Role created successfully with ID: {}", savedRole.getId());
        BeanUtils.copyProperties(savedRole, roleDTO);
        return roleDTO;
    }

    @Override
    @Transactional
    public RoleDTO updateRole(Long id, RoleDTO roleDTO) {
        logger.info("Updating role with ID: {}", id);
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> {
                    logger.error("Role not found: {}", id);
                    return new EntityNotFoundException("角色不存在");
                });

        if (!role.getName().equals(roleDTO.getName()) && 
            roleRepository.existsByName(roleDTO.getName())) {
            logger.error("Role name already exists: {}", roleDTO.getName());
            throw new IllegalArgumentException("角色名称已存在");
        }

        BeanUtils.copyProperties(roleDTO, role);

        if (roleDTO.getPermissionIds() != null) {
            logger.debug("Updating permissions for role: {}", id);
            Set<Permission> permissions = new HashSet<>(permissionRepository.findAllById(roleDTO.getPermissionIds()));
            role.setPermissions(permissions);
        }

        Role updatedRole = roleRepository.save(role);
        logger.info("Role updated successfully: {}", id);
        BeanUtils.copyProperties(updatedRole, roleDTO);
        return roleDTO;
    }

    @Override
    @Transactional
    public void deleteRole(Long id) {
        logger.info("Deleting role with ID: {}", id);
        if (!roleRepository.existsById(id)) {
            logger.error("Role not found: {}", id);
            throw new EntityNotFoundException("角色不存在");
        }
        roleRepository.deleteById(id);
        logger.info("Role deleted successfully: {}", id);
    }

    @Override
    public RoleDTO getRoleById(Long id) {
        logger.debug("Fetching role by ID: {}", id);
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> {
                    logger.error("Role not found: {}", id);
                    return new EntityNotFoundException("角色不存在");
                });
        RoleDTO roleDTO = new RoleDTO();
        BeanUtils.copyProperties(role, roleDTO);
        return roleDTO;
    }

    @Override
    public Page<RoleDTO> getAllRoles(Pageable pageable) {
        logger.debug("Fetching all roles with pagination: {}", pageable);
        return roleRepository.findAll(pageable)
                .map(role -> {
                    RoleDTO roleDTO = new RoleDTO();
                    BeanUtils.copyProperties(role, roleDTO);
                    return roleDTO;
                });
    }

    @Override
    @Transactional
    public RoleDTO assignPermissions(Long roleId, Set<Long> permissionIds) {
        logger.info("Assigning {} permissions to role: {}", permissionIds.size(), roleId);
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> {
                    logger.error("Role not found: {}", roleId);
                    return new EntityNotFoundException("角色不存在");
                });
        
        Set<Permission> permissions = new HashSet<>(permissionRepository.findAllById(permissionIds));
        role.setPermissions(permissions);
        
        Role updatedRole = roleRepository.save(role);
        logger.info("Permissions assigned successfully to role: {}", roleId);
        RoleDTO roleDTO = new RoleDTO();
        BeanUtils.copyProperties(updatedRole, roleDTO);
        return roleDTO;
    }
} 